const customKey = '__dataType'

function replacer(key: string, value: any): any {
  if (value instanceof Map) {
    return {
      [customKey]: 'Map',
      value: Array.from(value.entries()) // or with spread: value: [...value]
    }
  } else if (value instanceof Set) {
    return {
      [customKey]: 'Set',
      value: Array.from(value) // or with spread: value: [...value]
    }
  } else {
    return value
  }
}

function reviver(key: string, value: any): any {
  if (typeof value === 'object' && value !== null) {
    if (value[customKey] === 'Map') {
      return new Map(value.value)
    } else if (value[customKey] === 'Set') {
      return new Set(value.value)
    }
  }
  return value
}

export default class JsonUtils {
  public static stringify(obj: any): string {
    return JSON.stringify(obj, replacer)
  }

  public static parse(jsonStr: string) {
    return JSON.parse(jsonStr, reviver)
  }
}
